#include "epd_spi.h"
#include "esp_log.h"

#define EPD_SPI_TAG "EPD SPI"

spi_device_handle_t spi;

int epd_gpio_init(void)
{

    // gpio_set_direction(EPD_CS_PIN,GPIO_MODE_OUTPUT);
    // epd_delay_ms(10);

    gpio_reset_pin(EPD_DC_PIN);
    gpio_set_direction(EPD_DC_PIN, GPIO_MODE_OUTPUT);
    // epd_delay_ms(10);

    gpio_reset_pin(EPD_RST_PIN);
    gpio_set_direction(EPD_RST_PIN, GPIO_MODE_OUTPUT);
    // epd_delay_ms(10);

    gpio_reset_pin(EPD_BUSY_PIN);
    gpio_set_direction(EPD_BUSY_PIN, GPIO_MODE_INPUT);
    // epd_delay_ms(10);
    ESP_LOGI(EPD_SPI_TAG, "GPIO Init..\r\n");
    return 0;
}
int epd_spi_init(void)
{
    epd_gpio_init();

    esp_err_t ret;
    spi_bus_config_t buscfg = {
        .miso_io_num = -1,
        .mosi_io_num = PIN_NUM_MOSI,
        .sclk_io_num = PIN_NUM_CLK,
        .quadwp_io_num = -1,
        .quadhd_io_num = -1,
        .max_transfer_sz = PARALLEL_LINES * 320 * 2 + 8};
    spi_device_interface_config_t devcfg = {
        .clock_speed_hz = 0.5 * 1000 * 1000, // Clock out at 10 MHz
        .mode = 0,                           // SPI mode 0
        .spics_io_num = EPD_CS_PIN,          // CS pin
        .queue_size = 7,                     // We want to be able to queue 7 transactions at a time
        // .pre_cb=lcd_spi_pre_transfer_callback,  //Specify pre-transfer callback to handle D/C line
    };
    // Initialize the SPI bus
    ret = spi_bus_initialize(EPD_HOST, &buscfg, SPI_DMA_CH_AUTO);
    ESP_ERROR_CHECK(ret);
    // Attach the e-Paper to the SPI bus
    ret = spi_bus_add_device(EPD_HOST, &devcfg, &spi);
    ESP_ERROR_CHECK(ret);

    return 0;
}

void epd_spi_write_byte(uint8_t value)
{
    esp_err_t ret;
    spi_transaction_t t;
    memset(&t, 0, sizeof(t)); // Zero out the transaction
    t.length = 8;             // Command is 8 bits
    t.tx_buffer = &value;     // The data is the cmd itself
    // t.user=(void*)0;                //D/C needs to be set to 0
    ret = spi_device_polling_transmit(spi, &t); // Transmit!
    assert(ret == ESP_OK);                      // Should have had no issues.
}

int epd_module_init(void)
{
    epd_gpio_write(EPD_DC_PIN, 0);
    epd_gpio_write(EPD_CS_PIN, 0);
    epd_gpio_write(EPD_RST_PIN, 1);
    return 0;
}

void epd_module_exit(void)
{
    epd_gpio_write(EPD_DC_PIN, 0);
    epd_gpio_write(EPD_CS_PIN, 0);

    // close 5V
    epd_gpio_write(EPD_RST_PIN, 0);
}
